package com.isp.common.model.vo;


import com.fasterxml.jackson.annotation.JsonIgnore;
import com.isp.common.model.ResultCode;
import com.isp.common.model.enums.SystemCodeEnum;
import com.isp.common.model.exception.IBizException;

import java.io.Serializable;

/**
 * 统一返回值
 *
 * @param <T>
 * @author Linsy
 * @version 1.0
 * @created 2024/6/20
 */
public class Result<T> implements Serializable {
    private static final long serialVersionUID = -7452311826505540337L;
    /**
     * 响应code
     */
    private int ret;
    /**
     * 响应的错误信息
     */
    private String msg;
    /**
     * 响应数据
     */
    private T data;

    public static <T> Result<T> success() {
        return new Result<>();
    }

    /**
     * 成功,默认状态码,返回消息,自定义返回数据
     *
     * @param data 自定义返回数据
     * @param <T>  返回类泛型,不能为String
     * @return 通用返回Result
     */
    public static <T> Result<T> success(T data) {
        return new Result<>(data);
    }

    /**
     * 成功,默认状态码,自定义返回消息,返回数据
     *
     * @param msg  自定义返回消息
     * @param data 自定义返回数据
     * @param <T>  返回类泛型
     * @return 通用返回Result
     */
    public static <T> Result<T> success(String msg, T data) {
        return new Result<>(msg, data);
    }

    /**
     * 成功,默认状态码,自定义返回消息,无返回数据
     *
     * @param msg 自定义返回消息
     * @param <T> 返回类泛型
     * @return 通用返回Result
     */
    public static <T> Result<T> success(String msg) {
        return new Result<>(msg);
    }

    /**
     * 失败,默认状态码,返回消息,无返回数据
     *
     * @param <T> 返回类泛型
     * @return 通用返回Result
     */
    public static <T> Result<T> error() {
        return new Result<>(SystemCodeEnum.ERROR);
    }

    /**
     * 失败,默认状态码,自定义返回消息,无返回数据
     *
     * @param <T> 返回类泛型
     * @return 通用返回Result
     */
    public static <T> Result<T> error(String msg) {
        return new Result<>(SystemCodeEnum.ERROR.getRet(), msg);
    }

    /**
     * 失败,自定义状态码,返回消息,无返回数据
     *
     * @param ret 自定义状态码
     * @param msg 自定义返回消息
     * @param <T> 返回类泛型
     * @return 通用返回Result
     */
    public static <T> Result<T> error(int ret, String msg) {
        return new Result<>(ret, msg);
    }

    /**
     * 失败,使用CodeMsg状态码,返回消息,无返回数据
     *
     * @param resultCode CodeMsg,参数如下:
     *                   <p> ret 状态码
     *                   <p> msg  返回消息
     * @param <T>        返回类泛型
     * @return 通用返回Result
     */
    public static <T> Result<T> error(ResultCode resultCode) {
        return new Result<>(resultCode);
    }

    /**
     * 成功构造器,无返回数据
     */
    private Result() {
        this(SystemCodeEnum.SUCCESS);
    }

    /**
     * 成功构造器,自定义返回数据
     *
     * @param data 返回数据
     */
    private Result(T data) {
        this(SystemCodeEnum.SUCCESS, data);
    }

    /**
     * 成功构造器,自定义返回消息,无返回数据
     *
     * @param msg 返回消息
     */
    private Result(String msg) {
        this(SystemCodeEnum.SUCCESS.getRet(), msg);
    }

    /**
     * 构造器,自定义状态码,返回消息
     *
     * @param ret 状态码
     * @param msg 返回消息
     */
    private Result(int ret, String msg) {
        this.ret = ret;
        this.msg = msg;
    }

    /**
     * 成功构造器,自定义返回信息,返回数据
     *
     * @param msg  返回信息
     * @param data 返回数据
     */
    private Result(String msg, T data) {
        this(SystemCodeEnum.SUCCESS.getRet(), msg, data);
    }

    /**
     * 构造器,自定义状态码,返回消息,返回数据
     *
     * @param ret  状态码
     * @param msg  返回消息
     * @param data 返回数据
     */
    private Result(int ret, String msg, T data) {
        this(ret, msg);
        this.data = data;
    }

    /**
     * 构造器,使用CodeMsg状态码与返回信息,自定义返回数据
     *
     * @param resultCode CodeMsg,参数如下:
     *                   <p> ret 状态码
     *                   <p> msg  返回消息
     * @param data       返回数据
     */
    private Result(ResultCode resultCode, T data) {
        this(resultCode);
        this.data = data;
    }

    /**
     * 构造器,使用CodeMsg状态码与返回信息
     *
     * @param resultCode CodeMsg,参数如下:
     *                   <p> ret 状态码
     *                   <p> msg  返回消息
     */
    private Result(ResultCode resultCode) {
        this(resultCode.getRet(), resultCode.getMsg());
    }

    public static <T> Result<T> bizException(Exception e) {
        if (e instanceof IBizException) {
            IBizException bizException = (IBizException) e;
            return new Result<>(bizException.getCode(), bizException.getMessage());
        } else {
            return new Result<>(SystemCodeEnum.SERVER_ERROR.getRet(), e.getMessage());
        }
    }

    @JsonIgnore
    public boolean isSuccess() {
        return SystemCodeEnum.SUCCESS.getRet().equals(this.ret);
    }

    /**
     * 失败
     *
     * @return true/false
     */
    @JsonIgnore
    public boolean isFail() {
        return !isSuccess();
    }

    public int getRet() {
        return ret;
    }

    public void setRet(int ret) {
        this.ret = ret;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}